package com.yami.shop.personnft.api.controller;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.common.util.PageParam;
import com.yami.shop.common.util.RedisUtil;
import com.yami.shop.common.util.StringUtils;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.personnft.common.controller.BaseController;
import com.yami.shop.personnft.common.service.PersonNftApplyService;
import com.yami.shop.personnft.common.service.PersonNftService;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.security.common.util.AuthUserContext;
import com.yami.shop.service.*;
import com.yami.shop.webservice.common.service.WapiUserService;
import groovy.lang.Tuple;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * spu信息
 *
 * @author FrozenWatermelon
 * @date 2020-10-28 15:27:24
 */
@RestController("appPersonnftApplyDtcController")
@RequestMapping("/dtc/app/personnftApply")
@Tag(name = "app-personnftApply信息")
@AllArgsConstructor
@Slf4j
public class PersonnftDtcApplyController extends BaseController {
    @Autowired
    private PersonNftApplyService personNftApplyService;
    @Autowired
    private UserService userService;
    @Autowired
    private MeltCloudUserRemarkService userRemarkService;
    @Autowired
    private WapiUserService wapiUserService;
    @Autowired
    private ChannelUserRelationRecordService channelUserRelationRecordService;
    private final ShopDetailService shopDetailService;
    @Autowired
    private BlockchainService blockchainService;
    @Autowired
    private PersonNftService personNftService;
    @Autowired
    private ShopConfig shopConfig;
    /**
     * "content": "1"
     *
     * @param personNftApply
     * @return
     */
    @GetMapping("/selectApplyCount")
    @Operation(summary = "查询待接受转增数量", description = "转增")
    public ServerResponseEntity<Integer> selectApplyCount(PersonNftApply personNftApply) throws Exception {
        String userId = SecurityUtils.getUser().getUserId();
        if (StringUtils.isEmpty(RedisUtil.get("channelCode::" + userId))) {
            throw new YamiShopBindException("yami.chain.getcheck.fail");
        }
        personNftApply.setToUserId(userId);
        List<PersonNftApply> page = personNftApplyService.listByParam(personNftApply);
        return ServerResponseEntity.success(page.size());
    }

    /**
     * 查询待审核详情
     *
     * @param id
     * @return
     */
    @SneakyThrows
    @GetMapping("/selectApplyById")
    @Operation(summary = "查询详情", description = "转增")
    public ServerResponseEntity<JSONObject> selectApplyById(@RequestParam String id) {
        if (ObjectUtil.isNull(id)) {
            throw new YamiShopBindException("yami.sys.illegalArgument");
        }
        String userId = SecurityUtils.getUser().getUserId();
        if (StringUtils.isEmpty(RedisUtil.get("channelCode::" + userId))) {
            throw new YamiShopBindException("yami.chain.getcheck.fail");
        }
        PersonNftApply personNftApply = personNftApplyService.getinfoById(id);
        JSONObject map = JSONObject.parseObject(JSONObject.toJSONString(personNftApply));
        String mall4JChannel = shopConfig.getMall4JChannel();
        if(StrUtil.isNotEmpty(mall4JChannel) && StringUtils.matches(personNftApply.getChannelCode(), Arrays.asList(mall4JChannel.split(",")))){
            map.put("power", 0);
            Object o = RedisUtil.get("applyIssue::" + personNftApply.getDenomId());
            if(ObjectUtil.isNull(o)){
                personNftService.getApplyIssueNftInfoByDenomId(personNftApply.getDenomId());
                o = RedisUtil.get("applyIssue::" + personNftApply.getDenomId());
            }
            JSONObject obj = JSONObject.parseObject(o.toString());
            map.put("shortUrl",obj.getString("imgUrl"));
            map.put("dawName",obj.getString("dawName"));
            map.put("publishTime",ObjectUtil.isNotEmpty(obj.getString("createTime"))?obj.getString("createTime").substring(0,10):null);
        }else{
            map.put("power", personNftApply.getCount());
        }
        if (personNftApply.getToUserId() != null) {
            String toUserId = personNftApply.getToUserId();
            User toUser = userService.getUserByUserId(toUserId);
            if (Objects.nonNull(toUser) && !toUserId.equals(userId)) {
                MeltCloudUserRemark one = userRemarkService.getOne(Wrappers.lambdaQuery(MeltCloudUserRemark.class).eq(MeltCloudUserRemark::getType, 1).eq(MeltCloudUserRemark::getUserId, userId).eq(MeltCloudUserRemark::getObjId, toUserId));
                if (Objects.nonNull(one) && StringUtils.isNotEmpty(one.getRemark())) {
                    toUser.setNickName(one.getRemark());
                }
            }
            map.put("toUser", toUser);
        }
        if (personNftApply.getUserId() != null) {
            User user = userService.getUserByUserId(personNftApply.getUserId());
            if (Objects.nonNull(user) && !userId.equals(personNftApply.getUserId())) {
                MeltCloudUserRemark one = userRemarkService.getOne(Wrappers.lambdaQuery(MeltCloudUserRemark.class).eq(MeltCloudUserRemark::getType, 1).eq(MeltCloudUserRemark::getUserId, userId).eq(MeltCloudUserRemark::getObjId, personNftApply.getUserId()));
                if (Objects.nonNull(one) && StringUtils.isNotEmpty(one.getRemark())) {
                    user.setNickName(one.getRemark());
                }
            }
            map.put("user", user);
        }
        return ServerResponseEntity.success(map);
    }

    /**
     * "转增接受或者拒收
     *
     * @param id,type 1接受2拒收
     * @return
     */
    @GetMapping("/updateTransferApply")
    @Operation(summary = "转增接受或者拒收", description = "转增")
    public ServerResponseEntity updateTransferApply(@RequestParam("id") String id, @RequestParam("type") String type) {
        if (StringUtils.isEmpty(id) && StringUtils.isEmpty(type)) {
            throw new YamiShopBindException("yami.sys.illegalArgument");
        }
        if (!type.equals("1") && !type.equals("2")) {
            throw new YamiShopBindException("yami.sys.illegalArgument");
        }
        String userId = SecurityUtils.getUser().getUserId();
        try {
            PersonNftApply personNftApply = personNftApplyService.getinfoById(id);
            if (personNftApply.getStatus() != 0) {
                throw new YamiShopBindException("yami.dtc.status.error");
            }
            if (type.equals("1")) {
                // 判断用户是否有钱包
                Boolean hasAllAddress = channelUserRelationRecordService.isHasAllAddress(userId, personNftApply.getChainCode(), personNftApply.getChannelCode(), personNftApply.getChannelType());
                if (!hasAllAddress) {
                    Blockchain infoByCode = blockchainService.getInfoByCode(personNftApply.getChainCode());
                    ShopDetail shopDetailByShopCode = shopDetailService.getShopDetailByShopCode(personNftApply.getChannelCode());
                    // 创建钱包
                    throw new YamiShopBindException("请先添加" + shopDetailByShopCode.getShopShortName() + "对应" + infoByCode.getName() + "的钱包");
                }
            }
            personNftApply.setType(type);
            personNftApplyService.updateTransferApply(personNftApply);
            return ServerResponseEntity.success();
        } catch (YamiShopBindException e) {
            e.printStackTrace();
            return ServerResponseEntity.showFailMsg(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            throw new YamiShopBindException("yami.dtc.handle.error");
        }
    }

    /**
     * "content": "1"
     *
     * @param page
     * @param personNftApply
     * @return
     */
    @GetMapping("/selectListPage")
    @Operation(summary = "获取平台信息列表", description = "分页获取平台信息列表")
    public ServerResponseEntity<IPage<JSONObject>> selectListPage(PageParam<PersonNftApply> page, PersonNftApply personNftApply) {
        String userId = SecurityUtils.getUser().getUserId();
        Tuple<String> tuple = this.getChannelInfo(userId);
        personNftApply.setChainCode(tuple.get(2));
        personNftApply.setUserId(userId);
        IPage<PersonNftApply> page1 = personNftApplyService.page(page, personNftApply);
        List<PersonNftApply> records = page1.getRecords();
        IPage<JSONObject> res = new PageParam<>();
        res.setCurrent(page.getCurrent());
        List<JSONObject> personNfts = ObjectUtil.isNull(records) ? Lists.newArrayList() : JSONArray.parseArray(JSONObject.toJSONString(records), JSONObject.class);
        res.setRecords(personNfts);
        res.setSize(page.getSize());
        res.setTotal(page1.getTotal());
        return ServerResponseEntity.success(res);
    }

    @PostMapping("/saveTransferApplyBatch")
    @Operation(summary = "批量保存转增信息", description = "保存信息")
    public ServerResponseEntity<String> saveTransferApplyBatch(@Valid @RequestBody PersonNftApply personNftApply) {
        String userId = AuthUserContext.get().getUserId();
        if (ObjectUtil.isNull(personNftApply.getToUserId())) {
            throw new YamiShopBindException("yami.sys.illegalArgument");
        }
        if (ObjectUtil.isNull(personNftApply.getProductId())) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check.nft"));
        }
        if (ObjectUtil.isNull(personNftApply.getCount()) || personNftApply.getCount() == 0) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check.num"));
        }
        if (ObjectUtil.isNull(personNftApply.getToUserId())) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check.target"));
        }
        personNftApply.setUserId(userId);// 更具类型客户获取下游自己id
        if (personNftApply.getUserId().equals(personNftApply.getToUserId())) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check"));
        }
        Tuple<String> tuple = this.getChannelInfo(userId);
        if (tuple.get(1).equals(personNftApply.getToUserId())) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check"));
        }
        personNftApply.setChainCode(tuple.get(2));
        personNftApply.setChannelCode(tuple.get(0));
        personNftApply.setChannelType(tuple.get(3));
        try {
            String id = personNftApplyService.saveTransferApply(personNftApply);
            return ServerResponseEntity.success(id);
        } catch (YamiShopBindException e) {
            return ServerResponseEntity.showFailMsg(e.getMessage());
        } catch (MailException e) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.check.error"));
        }
    }

    @PostMapping("/saveTransferHwjApplyBatch")
    @Operation(summary = "保存划转申请信息", description = "保存信息")
    public ServerResponseEntity saveTransferHwjApplyBatch(@Valid @RequestBody PersonNftApply personNftApply) throws Exception {
        if (ObjectUtil.isNull(personNftApply.getProductId()) || ObjectUtil.isNull(personNftApply.getCount())) {
            throw new YamiShopBindException("yami.sys.illegalArgument");
        }
        if (personNftApply.getCount() == 0) {
            throw new YamiShopBindException("yami.personnft.thansfer.num.check");
        }
        String userId = SecurityUtils.getUser().getUserId();
        Tuple<String> tuple = this.getChannelInfo(userId);
        // 校验是
        User userByUserId = userService.getUserByUserId(userId);
        if (StrUtil.isEmpty(userByUserId.getIdNumber())) {
            throw new YamiShopBindException("yami.dtc.check.realname");
        }
        Map<String, Object> wapiUserIdByCardId = wapiUserService.getWapiUserIdByCardId(userByUserId.getIdNumber());
        if (Objects.isNull(wapiUserIdByCardId.get("userId"))) {
            throw new YamiShopBindException("yami.personnft.thansfer.hwj.account");
        }
        String hwjuserId = (String) wapiUserIdByCardId.get("userId");
        personNftApply.setHwjUserId(hwjuserId);
        personNftApply.setChainCode(tuple.get(2));
        personNftApply.setChannelCode(tuple.get(0));
        personNftApply.setChannelType(tuple.get(3));
        personNftApply.setUserId(userId);
        try {
            String id = personNftApplyService.saveTransferHwjApplyBatch(personNftApply);
            return ServerResponseEntity.success(id);
        } catch (YamiShopBindException e) {
            return ServerResponseEntity.showFailMsg(e.getMessage());
        } catch (MailException e) {
            return ServerResponseEntity.showFailMsg(I18nMessage.getMessage("yami.personnft.thansfer.error"));
        }
    }

    /**
     * "转增记录查询
     *
     * @param personNftApply
     * @return
     */
    @GetMapping("/selectTransferList")
    @Operation(summary = "分页获取转增记录列表", description = "转增")
    public ServerResponseEntity<IPage<Map<String, Object>>> selectTransferList(PageParam<PersonNftApply> page, PersonNftApply personNftApply) throws Exception {
        String userId = SecurityUtils.getUser().getUserId();
        if (StringUtils.isEmpty(RedisUtil.get("channelCode::" + userId))) {
            throw new YamiShopBindException("yami.chain.getcheck.fail");
        }
        personNftApply.setSceneType("1");
        if (personNftApply.getType().equals("1")) {
            personNftApply.setUserId(userId);
        } else {
            personNftApply.setToUserId(userId);
        }
        IPage<PersonNftApply> page1 = personNftApplyService.page(page, personNftApply);
        List<PersonNftApply> records = page1.getRecords();
        List<Map<String, Object>> resList = new ArrayList<>();
        Map<String, String> remarkMap = new HashMap<>();
        if (CollUtil.isNotEmpty(records)) {
            Set<String> userIds;
            if (personNftApply.getType().equals("1")) {
                userIds = records.stream().map(PersonNftApply::getToUserId).collect(Collectors.toSet());
            } else {
                userIds = records.stream().map(PersonNftApply::getUserId).collect(Collectors.toSet());
            }
            List<MeltCloudUserRemark> remarkList = userRemarkService.list(Wrappers.lambdaQuery(MeltCloudUserRemark.class).eq(MeltCloudUserRemark::getType, 1).eq(MeltCloudUserRemark::getUserId, userId).in(MeltCloudUserRemark::getObjId, userIds));
            remarkMap = remarkList.stream().collect(Collectors.toMap(MeltCloudUserRemark::getObjId, MeltCloudUserRemark::getRemark));
        }
        for (PersonNftApply apply : records) {
            if (personNftApply.getType().equals("1")) {
                if (StringUtils.isNotEmpty(apply.getToUserName()) && StringUtils.isNotEmpty(remarkMap.get(apply.getToUserId()))) {
                    apply.setToUserName(remarkMap.get(apply.getToUserId()));
                }
            } else {
                if (StringUtils.isNotEmpty(remarkMap.get(apply.getUserId()))) {
                    apply.setUserName(remarkMap.get(apply.getUserId()));
                }
            }
            if(apply.getProductId().equals(0l)){
                Object o = RedisUtil.get("applyIssue::" + apply.getDenomId());
                if(ObjectUtil.isNull(o)){
                    personNftService.getApplyIssueNftInfoByDenomId(apply.getDenomId());
                    o = RedisUtil.get("applyIssue::" + apply.getDenomId());
                }
                JSONObject obj = JSONObject.parseObject(o.toString());
                apply.setShortUrl(obj.getString("imgUrl"));
                apply.setDawName(obj.getString("dawName"));
                apply.setAuthor(obj.getString("author"));
                apply.setShopName(obj.getString("author"));
            }
            resList.add(StringUtils.obj2MapNotNull(apply));
        }
        IPage<Map<String, Object>> res = new PageParam<>();
        res.setCurrent(page.getCurrent());
        res.setRecords(resList);
        res.setSize(page.getSize());
        res.setTotal(page1.getTotal());
        return ServerResponseEntity.success(res);
    }

    /**
     * "划转记录查询
     *
     * @param personNftApply
     * @return
     */
    @GetMapping("/selectTransferToList")
    @Operation(summary = "分页获取转增记录列表", description = "转增")
    public ServerResponseEntity<IPage<Map<String, Object>>> selectTransferToList(PageParam<PersonNftApply> page, PersonNftApply personNftApply) throws Exception {
        String userId = SecurityUtils.getUser().getUserId();
        if (StringUtils.isEmpty(RedisUtil.get("channelCode::" + userId))) {
            throw new YamiShopBindException("yami.chain.getcheck.fail");
        }
        personNftApply.setUserId(userId);
        personNftApply.setSceneType("3");
        IPage<PersonNftApply> page1 = personNftApplyService.page(page, personNftApply);
        List<PersonNftApply> records = page1.getRecords();
        List<Map<String, Object>> resList = new ArrayList<>();
        for (PersonNftApply apply : records) {
            resList.add(StringUtils.obj2MapNotNull(apply));
        }
        IPage<Map<String, Object>> res = new PageParam<>();
        res.setCurrent(page.getCurrent());
        res.setRecords(resList);
        res.setSize(page.getSize());
        res.setTotal(page1.getTotal());
        return ServerResponseEntity.success(res);
    }
}
